﻿using System;
using System.Collections.Generic;
using System.Data;

using System.Text;


namespace QQZiFramework
{
    public abstract class IDBAccess : IDisposable
    {
        protected DBContext mContext;
        public IDBAccess(DBContext context)
        {
            mContext = context;
        }
        public abstract void Create(string connectionString);

        // /// <summary>
        // /// 字符串拼接函数(如果有)
        // /// </summary>
        // /// <returns></returns>
        // public virtual string ConcatFunction() { return null; }

        /// <summary>
        /// 字符串拼接的sql(与ConcatFunction必需有一个)
        /// </summary>
        /// <returns>
        public virtual string ConcatSql(params string[] args) { 
            return string.Join('+',args);
        }

        public abstract IDbConnection GetConnection();

        /// <summary>
        /// 手动开始事务
        /// </summary>
        public abstract void BeginTransaction();

        public abstract DataTable QueryTable(string text, CommandType cmdType, params System.Data.IDbDataParameter[] parameters);

        public abstract DataTable QueryTable(string sql);

        public abstract IDataReader QueryReader(string sql, CommandType cmdType, params System.Data.IDbDataParameter[] parameters);

        /// <summary>
        /// 组织分页查询sql
        /// </summary>
        /// <param name="select"></param>
        /// <param name="table"></param>
        /// <param name="where"></param>
        /// <param name="orderby"></param>
        /// <param name="start">起始位置，从1开始</param>
        /// <param name="end">结束位置</param>
        public abstract String PartQuerySql(string select, string table, string where, string orderby, int start, int end);

        // public abstract String PartQuerySql(string select, string table, string where, string orderby, IDbDataParameter pageIndex, IDbDataParameter pageSize);
        
        public abstract int ExecuteCommand(string text, CommandType cmdType, params System.Data.IDbDataParameter[] parameters);
        public abstract int ExecuteCommand(string sql);

        public abstract IDbDataParameter CreateParameter(string name, object value);

        public abstract object ExecScalar(string text, CommandType cmdType, params System.Data.IDbDataParameter[] parameters);
        public abstract object ExecScalar(string sql);

        /// <summary>
        /// 列别名处理，有些数据库会强制大小写，比如oracle，需要引引号
        /// </summary>
        /// <param name="dbFileName">数据库的名字，可能包含表名.字段名</param>
        /// <param name="entityFieldName">实体或者配置的名字</param>
        public virtual void AppendFieldAlaisName(ref string dbFileName, string entityFieldName)
        {
            string compareName;
            string[] arr = dbFileName.Split('.');
            if (arr.Length > 1) compareName = arr[1];
            else compareName = dbFileName;
            if (compareName != entityFieldName) dbFileName += " " + entityFieldName;
        }

        /// <summary>
        /// 自增标识（是否有自增功能）
        /// </summary>
        public abstract bool AotoIdentity { get; }

        /// <summary>
        /// 自增语句，如果AotoIdentity=false则在insert的时候赋值给主键（比如oracle），否则是在插入语句执行后再查询（比如sqlserver）
        /// </summary>
        public abstract string GetNewIdentitySql(string tableName);

        // <summary>
        /// 获取插入的自增主键值
        /// </summary>
        public abstract string GetInsertedIdentitySql(string tableName);

        public abstract void Commit();

        public abstract void Rollback();
        public abstract void Close();

        public abstract string GetLastSql();

        /// <summary>
        /// 获取转日期的语句表达式
        /// </summary>
        /// <returns></returns>
        public abstract string GetDateConverter(int length);

        /// <summary>
        /// 函数表达式
        /// </summary>
        /// <value></value>
        public abstract Dictionary<string, string> FunctionFormatMap { get; }

        /// <summary>
        /// 绑定参数是否可复用，比如in = @value or name = @value ，只生成一个参数，如果为false则生成多个参数
        /// </summary>
        /// <value></value>
        public virtual bool ParameterMultiplexing { get{ return true; } }

        public abstract void CreateTreeExtendTableIfNotExists(string treeTableName);
        public abstract void Dispose();

        /// <summary>
        /// 获取所有的表
        /// </summary>
        public abstract System.Collections.Generic.Dictionary<string, string> GetTables();

        /// <summary>
        /// 是否存在表
        /// </summary>
        public abstract bool IsTableExists(string tableName);

        /// <summary>
        /// 是否存在列
        /// </summary>
        public abstract bool IsColumnExists(string tableName, string columnName);

        /// <summary>
        /// 获取表的主键
        /// </summary>

        public abstract string[] GetTablePrimaryKeys(string tableName);

        /// <summary>
        /// 获取表的外键
        /// </summary>

        public abstract ForeignKeyItem[] GetTableForeignKeys(string tableName);

        /// <summary>
        /// 指量插入，dataTable需要与表的列名一至
        /// <param name="tableName">数据库的表名</param>
        /// <param name="dataTable"></param>
        /// </summary>
        public abstract void BulkInsert(string tableName, DataTable dataTable);

        /// <summary>
        /// 获取属性的类型转为数据库中定义的类型
        /// <param name="propertyType">C#的数据类型</param>
        /// </summary>
        public abstract string ConvertDataType(Type propertyType, bool withSize);

        /// <summary>
        /// 创建临时表（通常是根据DataTable)，返回表名（包含#）
        /// <param name="tableName">临时表名，不包含#</param>
        /// <param name="allColumns">所有字段</param>
        /// <param name="createPrimaryKey">指定某个列名为主键，可为空</param>
        /// </summary>
        public abstract string CreateTempTable(string tableName, DataColumn[] allColumns, DataColumn createPrimaryKey);

        /// <summary>
        /// 根据临时表的内容，更新物理表
        /// <param name="primaryKey">主键名</param>
        /// <param name="updateColumns">要更新的列</param>
        /// </summary>
        public abstract void UpdateByTempTable(string tableName, string tempTableFullName, DataColumn[] updateColumns, DataColumn primaryKeyColumn);


        /// <summary>
        /// 删除临时表
        /// <param name="tableName">临时表名，不包含#</param>
        /// </summary>
        public abstract void DropTempTable(string tableName);

    }


    public enum SqlLogMode
    {
        /// <summary>
        /// 不记录
        /// </summary>
        NoLog = 0,
        /// <summary>
        /// 记录除select之外的
        /// </summary>
        ExceptSelect = 1,
        /// <summary>
        /// 全部
        /// </summary>
        All = 2
    }
}
